package com.yhj.wchat.service.impl;

import com.yhj.wchat.config.AppConfig;
import com.yhj.wchat.constants.Constants;
import com.yhj.wchat.entity.dto.MessageSendDto;
import com.yhj.wchat.entity.dto.TokenUserInfoDto;
import com.yhj.wchat.entity.po.UserContactApply;
import com.yhj.wchat.entity.po.UserContactApplyNew;
import com.yhj.wchat.entity.po.UserContactNew;
import com.yhj.wchat.entity.po.UserInfo;
import com.yhj.wchat.entity.query.UserContactApplyNewQuery;
import com.yhj.wchat.entity.query.UserInfoQuery;
import com.yhj.wchat.entity.vo.ContactUserVO;
import com.yhj.wchat.entity.vo.SearchFriendVO;
import com.yhj.wchat.entity.vo.UserContactApplyNewMessageVO;
import com.yhj.wchat.entity.vo.UserInfoVO;
import com.yhj.wchat.exception.BusinessException;
import com.yhj.wchat.exception.ResponseCodeEnum;
import com.yhj.wchat.mapper.UserContactApplyNewMapper;
import com.yhj.wchat.mapper.UserInfoMapper;
import com.yhj.wchat.message.MessageHandler;
import com.yhj.wchat.message.MessageTypeEnum;
import com.yhj.wchat.mj.MessageSend2TypeEnum;
import com.yhj.wchat.mj.UserStatusEnum;
import com.yhj.wchat.redis.RedisComponent;
import com.yhj.wchat.service.UserInfoService;
import com.yhj.wchat.utils.ChannelContextUtils;
import com.yhj.wchat.utils.CopyTools;
import com.yhj.wchat.utils.StringTools;
import io.swagger.models.auth.In;
import lombok.Builder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class UserInfoServiceImpl implements UserInfoService {

    @Resource
    private UserInfoMapper userInfoMapper;
    @Resource
    private UserContactApplyNewMapper userContactApplyNewMapper;
    @Resource
    private MessageHandler messageHandler;
    @Resource
    private AppConfig appConfig;
    @Resource
    private RedisComponent redisComponent;
    @Resource
    private ChannelContextUtils channelContextUtils;

    @Override
    public void register(String email, String nickName, String password) {
        // 根据邮箱查询用户信息
        UserInfo userInfo= (UserInfo) this.userInfoMapper.selectByEmail(email);
        if (userInfo != null) {
            throw new RuntimeException("该邮箱已被注册");
        }
        // 注册用户
        Date curDate = new Date();
        String userId = StringTools.getRandomNumber(Constants.LENGTH_12);
        UserInfo user = new UserInfo();
        user.setUserId(userId);
        user.setEmail(email);
        user.setNickName(nickName);
        user.setPassword(password);
        user.setPassword(StringTools.encodeByMD5(password));
        user.setCreateTime(curDate);
        user.setLastLoginTime(curDate.getTime());
        user.setLastOffTime(curDate.getTime());
        user.setMeetingNo(StringTools.getMeetingNoOrMeetingId());
        user.setStatus(UserStatusEnum.ENABLE.getStatus());
        this.userInfoMapper.insert(user);

    }

    @Override
    public UserInfoVO login(String email, String password) {
        UserInfo userInfo = (UserInfo) userInfoMapper.selectByEmail(email);
        if (null == userInfo || !StringTools.encodeByMD5(password).equals(userInfo.getPassword())) {
            throw new BusinessException(ResponseCodeEnum.CODE_501);
        }
        if (UserStatusEnum.DISABLE.getStatus().equals(userInfo.getStatus())) {
            throw new BusinessException(ResponseCodeEnum.CODE_502);
        }
//		if (userInfo.getLastLoginTime()!= null && userInfo.getLastLoginTime() > userInfo.getLastOffTime()) {
//			throw new BusinessException(ResponseCodeEnum.CODE_503);
//		}
        TokenUserInfoDto tokenUserInfoDto = CopyTools.copy(userInfo, TokenUserInfoDto.class);
        String token =  StringTools.encodeByMD5(tokenUserInfoDto.getUserId() + StringTools.getRandomNumber(Constants.LENGTH_20));
        tokenUserInfoDto.setToken(token);
        tokenUserInfoDto.setAdmin(appConfig.getAdminEmails().contains(email));

        redisComponent.saveTokenUserInfoDto(tokenUserInfoDto);
        UserInfoVO userInfoVO = CopyTools.copy(userInfo, UserInfoVO.class);
        userInfoVO.setToken(token);
        userInfoVO.setAdmin(appConfig.getAdminEmails().contains(email));
        return userInfoVO;
    }

    @Override
    public Boolean logout(String userId) {
        try {
            redisComponent.clearTokenByUserId(userId);
            channelContextUtils.closeContext(userId);
            return true;
        }
        catch (Exception e) {
            return false;
        }


    }

    @Override
    public List<ContactUserVO> getUserContact(List<String> userIds) {
        List<ContactUserVO> users =userInfoMapper.selectContactUserInfo(userIds);
        return users;
    }

    @Override
    public List<SearchFriendVO> searchFriends(String searchKeyWord) {
        UserInfoQuery userInfoQuery = new UserInfoQuery();
        userInfoQuery.setNickNameFuzzy(searchKeyWord);
        List<UserInfo> list = userInfoMapper.selectList(userInfoQuery);
       // List<SearchFriendVO> searchFriendVOS =new ArrayList<>();
        List<SearchFriendVO> collect = list.stream().map(userInfo -> {
            SearchFriendVO searchFriendVO = new SearchFriendVO();
            searchFriendVO.setId(userInfo.getUserId());
            searchFriendVO.setName(userInfo.getNickName());
            searchFriendVO.setEmail(userInfo.getEmail());
            return searchFriendVO;
        }).collect(Collectors.toList());
        return collect;
    }

    @Override
    @Transactional
    public Boolean sendAddFriend(String userId, String receiverId, String content) {
        UserContactApplyNew userContactApplyNew = new UserContactApplyNew();
        userContactApplyNew.setApplyUserId(userId);
        userContactApplyNew.setReceiveUserId(receiverId);
        userContactApplyNew.setLastApplyTime(new Date().getTime());
        userContactApplyNew.setStatus(1);
        userContactApplyNew.setContent(content);
        userContactApplyNew.setType(1);
        UserContactApplyNew row = userContactApplyNewMapper.selectRow(userId,receiverId);
        if (row != null && row.getStatus() == 1) {
            throw new BusinessException(ResponseCodeEnum.CODE_602);
        }
        else if (row != null && row.getStatus() == 2) {
            throw new BusinessException(ResponseCodeEnum.CODE_604);
        }
        userContactApplyNewMapper.insert(userContactApplyNew);
        UserInfo userInfo = (UserInfo) userInfoMapper.selectByUserId(userId);
        String name = userInfo.getNickName();
        UserContactApplyNewMessageVO userContactApplyNewMessageVO = new UserContactApplyNewMessageVO();
        userContactApplyNewMessageVO.setId(userId);
        userContactApplyNewMessageVO.setMessage(content);
        userContactApplyNewMessageVO.setFromName(name);
        MessageSendDto messageSendDto = MessageSendDto.builder()
                .messageSend2Type(MessageSend2TypeEnum.USER.getType())
                .messageType(MessageTypeEnum.USER_CONTACT_APPLY.getType())
                .sendUserId(userId)
                .receiveUserId(receiverId)
                .sendTime(System.currentTimeMillis())
                .messageContent(userContactApplyNewMessageVO)
                .build();
        messageHandler.sendMessage(messageSendDto);
        return true;
    }

    @Override
    public List<UserContactApplyNewMessageVO> getApplyFriend(String userId) {
        UserContactApplyNewQuery userContactApplyNewQuery = new UserContactApplyNewQuery();
        userContactApplyNewQuery.setReceiveUserId(userId);
        userContactApplyNewQuery.setStatus(1);
        userContactApplyNewQuery.setType(1);
        List<UserContactApplyNew> list = (List<UserContactApplyNew>) userContactApplyNewMapper.selectList(userContactApplyNewQuery);
        List<UserContactApplyNewMessageVO> users = list.stream().map(userContactApplyNew -> {
            UserContactApplyNewMessageVO user = new UserContactApplyNewMessageVO();
            user.setId(userContactApplyNew.getApplyUserId());
            user.setMessage(userContactApplyNew.getContent());
            UserInfo userInfo = (UserInfo) userInfoMapper.selectByUserId(userContactApplyNew.getApplyUserId());
            user.setFromName(userInfo.getNickName());
            return user;
        }).collect(Collectors.toList());
        return users;
    }
}
